package com.hb.test

import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import java.util.stream.Collectors
import java.util.stream.Stream

fun getAddressFromDB2(userId:Long):CompletableFuture<Address>{
    //返回的是CompletableFuture<Address>
    //println("userId : $userId getAddressFromDB ")
    return CompletableFuture.supplyAsync{
        Thread.sleep(1000)
        Address(userId,"杭州")
    }
}

fun getGoodsFromDB2(goodsId:Long):CompletableFuture<Goods>{
    //println("goodsId : $goodsId getGoodsFromDB ")
    //返回的是CompletableFuture<Address>
    return CompletableFuture.supplyAsync{
        Thread.sleep(1000)
        Goods(goodsId,"好吃的食物",10)
    }
}

fun doOrder2(goods: Goods,address: Address):CompletableFuture<Long>{
    //println("goods : $goods address $address ")
    return CompletableFuture.supplyAsync{
        Thread.sleep(1000)
        1L
    }
}


/**
 * 在java8之后我们确实可以使用CompletableFuture来写异步非阻塞代码
 * 但是我们发现对CompletableFuture的操作却不怎么直观，比如下面的合并操作，还需要借助Stream来得到结果，
 * 这让我们的开发变得繁琐，不容易理解
 */
fun main() {
    val start = System.currentTimeMillis()

    val goodsFromDB2 = getGoodsFromDB2(2)
    val addressFromDB2 = getAddressFromDB2(1)

    CompletableFuture.allOf(goodsFromDB2,addressFromDB2).thenApply {
       //保证前两个IO操作返回结果后在执行
        Stream.of(goodsFromDB2,addressFromDB2).map {
            it.join()
        }.collect(Collectors.toList<Any>())
    }.thenApply {
        doOrder2(it[0] as Goods ,it[1] as Address)
    }.join()


    val end = System.currentTimeMillis()
    val toSeconds = TimeUnit.MILLISECONDS.toSeconds(end - start)
    println("耗时： $toSeconds s")
}